//
// Created by Administrator on 2022/6/9.
//

#include "timer/WheelTimer.h"

void WheelTimer::run() {
    while (true) {
        std::unique_lock<std::mutex> lk(wheelMutex);
        if (wheelCond.wait_for(lk, tickDuration, [this] { return stop.load(); })) {
            break;
        } else {
            if (stop.load()) break;
            // execute expired tasks
            auto& st = buckets[tickIndex].nodes;
            for (auto st_iter = st.begin(); st_iter != st.end();) {
                if (numTurns >= st_iter->turn) {
                    st_iter->func();
                    auto iter = taskMap.find(st_iter->id);
                    ++st_iter;
                    st.erase(iter->second.second);
                    taskMap.erase(iter);
                } else {
                    break;
                }
            }
            std::cout << "timeout" << std::endl;
            // move pointer one tick
            tickIndex++;
            if (tickIndex == tickCount) {
                tickIndex = 0;
                numTurns++;
            }
        }
    }
}

// 取消定时任务
bool WheelTimer::cancelTask(TaskID taskId) {
    std::lock_guard<std::mutex> lk(wheelMutex);
    auto iter = taskMap.find(taskId);
    if (iter == taskMap.end()) {
        return false;
    }
    buckets[iter->second.first].nodes.erase(iter->second.second);
    taskMap.erase(iter);
    return true;
}

// 检查定时任务是否还未执行
bool WheelTimer::checkTask(TaskID taskId) {
    std::lock_guard<std::mutex> lk(wheelMutex);
    return taskMap.count(taskId);
}

WheelTimer::~WheelTimer() {
    stop.store(true);
    wheelCond.notify_one();
    worker.join();
}
